package com.boonya.lab.netty.websocket.utils;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
import java.util.Base64;

/**
 * 对称加解密AES算法
 */
public class AESUtils {

    private static final String ALGORITHM = "AES/CBC/PKCS5Padding";
    private static final String CHARSET = "UTF-8";

    /**
     * 解密客户端发送的数据
     *
     * @param encryptedBase64 客户端加密的Base64字符串(包含IV)
     * @param secretKey       32字节的共享密钥
     * @return 解密后的原始字符串
     */
    public static String decrypt(String encryptedBase64, String secretKey) throws Exception {
        // Base64解码
        byte[] combined = Base64.getDecoder().decode(encryptedBase64);

        // 提取IV (前16字节)
        byte[] iv = new byte[16];
        System.arraycopy(combined, 0, iv, 0, iv.length);
        IvParameterSpec ivSpec = new IvParameterSpec(iv);

        // 提取加密数据
        byte[] encrypted = new byte[combined.length - iv.length];
        System.arraycopy(combined, iv.length, encrypted, 0, encrypted.length);

        // 准备密钥
        SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(CHARSET), "AES");

        // 解密
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
        byte[] decrypted = cipher.doFinal(encrypted);

        return new String(decrypted, CHARSET);
    }

    // 加密方法
    public static String encrypt(String plaintext, String secretKey) throws Exception {
        // 生成随机IV
        byte[] iv = new byte[16];
        new SecureRandom().nextBytes(iv);
        IvParameterSpec ivSpec = new IvParameterSpec(iv);

        // 准备密钥
        SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(CHARSET), "AES");

        // 加密
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
        byte[] encrypted = cipher.doFinal(plaintext.getBytes(CHARSET));

        // 组合IV和加密数据 (IV + encrypted)
        byte[] combined = new byte[iv.length + encrypted.length];
        System.arraycopy(iv, 0, combined, 0, iv.length);
        System.arraycopy(encrypted, 0, combined, iv.length, encrypted.length);

        return Base64.getEncoder().encodeToString(combined);
    }
}
